﻿using AngleExpress.software;
using AngleExpress.utils;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.Extensions;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AngleExpress.web
{

    delegate void BeforeLogin(WebDriverWait wait);

    class BaiShiLoginTaskParam
    {
        internal BeforeLogin beforeLogin { get; set; }
        internal string username { get; set; }
        internal string password { get; set; }
        internal ManualResetEvent manualResetEvent { get; set; }
    }

    class DriverException : Exception
    {
    }

    abstract class WebOpener : ISoftware, IDisposable
    {
        IWebDriver driver;
        private bool disposedValue;
        private readonly string driverName;

        protected WebOpener(string driverName)
        {
            this.driverName = driverName;
        }

        protected abstract IWebDriver initDriver();

        void openUrl(string url)
        {
            if (driver == null)
            {
                try { driver = initDriver(); }
                catch (Exception)
                {
                    throw new DriverException();
                }
                driver.Manage().Window.Maximize();
                driver.Navigate().GoToUrl(url);
            }
            else
            {
                try { driver.ExecuteJavaScript("window.open('" + url + "')"); }
                catch (NoSuchWindowException)
                {
                    driver = driver.SwitchTo().Window(driver.WindowHandles[0]);
                    driver.ExecuteJavaScript("window.open('" + url + "')");
                    var last = driver.WindowHandles.Count - 1;
                    driver = driver.SwitchTo().Window(driver.WindowHandles[last]);
                    return;
                }
                catch (WebDriverException e)
                {
                    //如果手动关闭了浏览器
                    if (e.Message.StartsWith("chrome not reachable") || e.Message == "Failed to decode response from marionette")
                    {
                        driver.Quit();
                        driver = null;
                        openUrl(url);
                    }
                    //浏览器与driver版本不一致
                    else if(e.Message.Contains("this version") && e.Message.Contains("only supports"))
                    {
                        throw new DriverException();
                    }
                    else
                    {
                        throw e;
                    }

                }
                var index = driver.WindowHandles.Count - 1;
                driver = driver.SwitchTo().Window(driver.WindowHandles[index]);
            }

        }


        private void loginBaiShiExpress(object param)
        {
            BaiShiLoginTaskParam taskParam = param as BaiShiLoginTaskParam;
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

            try
            {
                taskParam.beforeLogin?.Invoke(wait);
                wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".login_type img")));
                var tapElement = driver.FindElement(By.CssSelector(".login_type img"));
                tapElement.Click();

                wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[placeholder=密码]")));
                var passElement = driver.FindElement(By.CssSelector(@"input[placeholder=密码]"));
                passElement.SendKeys(taskParam.password);

                wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[placeholder=百世账号\/手机号\/域账号]")));
                var usenameElement = driver.FindElement(By.CssSelector(@"input[placeholder=百世账号\/手机号\/域账号]"));
                usenameElement.SendKeys(taskParam.username);
            }
            catch (WebDriverTimeoutException)
            {
            }
            finally
            {
                taskParam.manualResetEvent.Set();
            }

        }

        private void CheckLoginSuccess(object param)
        {

            ManualResetEvent manualResetEvent = param as ManualResetEvent;
            WebDriverWait wait_first = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
            try
            {
                wait_first.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.TitleContains("登录-请选择一个授权"));
                manualResetEvent.Set();
            }
            catch (WebDriverTimeoutException)
            {

            }
        }

        //百世协和，登录百世账号
        public void OpenBaishiXieHe(string username, string password, string otherParam)
        {
            openUrl("http://xh.800best.com");
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            BaiShiLoginTaskParam taskParam = new BaiShiLoginTaskParam() { beforeLogin = null, username = username, password = password, manualResetEvent = manualResetEvent };

            Task.Factory.StartNew(new Action<object>(loginBaiShiExpress), taskParam);
            Task.Factory.StartNew(new Action<object>(CheckLoginSuccess), manualResetEvent);
            manualResetEvent.WaitOne();
            Console.WriteLine("over");
        }

        /// <summary>
        /// 百世掌柜,和百世协和界面一样
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public void OpenBaishiZhangGui(string username, string password, string otherParam)
        {
            openUrl("http://S9.800best.com");
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            BaiShiLoginTaskParam taskParam = new BaiShiLoginTaskParam() { beforeLogin = null, username = username, password = password, manualResetEvent = manualResetEvent };

            Task.Factory.StartNew(new Action<object>(loginBaiShiExpress), taskParam);
            Task.Factory.StartNew(new Action<object>(CheckLoginSuccess), manualResetEvent);
            manualResetEvent.WaitOne();
            Console.WriteLine("over");
        }

        //百世crm
        public void OpenBaishiCrm(string username, string password, string otherParam)
        {
            openUrl("http://icrm.800best.com");

            BeforeLogin beforeLogin = (WebDriverWait wait) =>
            {
                wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".div-tip-con .title-type")));
                var tap1 = driver.FindElement(By.CssSelector(".div-tip-con .title-type"));
                tap1.Click();
            };

            ManualResetEvent manualResetEvent = new ManualResetEvent(false);
            BaiShiLoginTaskParam taskParam = new BaiShiLoginTaskParam() { beforeLogin = beforeLogin, username = username, password = password, manualResetEvent = manualResetEvent };

            Task.Factory.StartNew(new Action<object>(loginBaiShiExpress), taskParam);
            Task.Factory.StartNew(new Action<object>(CheckLoginSuccess), manualResetEvent);
            manualResetEvent.WaitOne();
            Console.WriteLine("over");
        }

        public void OpenBaishi123(string username, string password, string otherParam)
        {
            openUrl("http://123.800bestex.com/");
        }

        //申通网点管家
        public void OpenWangDianGuanJia(string username, string password, string otherParam)
        {
            openUrl("http://sso.sto-express.cn/Authenticate/Login?systemCode=SITE_KEEPER&returnUrl=/index");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector("section.code > div > div > div.tab > span:nth-child(3)")));
            var tapElement = driver.FindElement(By.CssSelector("section.code > div > div > div.tab > span:nth-child(3)"));
            tapElement.Click();

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#userName")));
            var passElement = driver.FindElement(By.CssSelector(@"#userName"));
            passElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#passWord")));
            var usenameElement = driver.FindElement(By.CssSelector(@"#passWord"));
            usenameElement.SendKeys(password);
        }

        //韵达韵智星
        public void OpenYunDaYunZhiXing(string username, string password, string otherParam)
        {
            openUrl("https://aikf.yundasys.com/client/index");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#form-username")));
            var passElement = driver.FindElement(By.CssSelector(@"#form-username"));
            passElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#form-password")));
            var usenameElement = driver.FindElement(By.CssSelector(@"#form-password"));
            usenameElement.SendKeys(password);
        }

        //苏宁
        public void OpenSuNingExpress(string username, string password, string otherParam)
        {
            openUrl("http://eds.suning.com/eds-web/user/p/login.action");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#userId")));
            var passElement = driver.FindElement(By.CssSelector(@"#userId"));
            passElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#pwd")));
            var usenameElement = driver.FindElement(By.CssSelector(@"#pwd"));
            usenameElement.SendKeys(password);
            driver.ExecuteJavaScript("var box=document.getElementById('passwordeye');box.remove();");

        }

        //中通快递
        public void OpenZhongTongExpress(string username, string password, string otherParam)
        {
            string url = @"https://sso.zto.com/oauth2/authorize?appid=ztoj2ANGOKV7qSjex33CxHJA&redirect_uri=https%3A%2F%2Fztbsapi.zt-express.com%2Fportal%2Fuser%2Flogin%3Fredirect_uri%3Dhttps%253A%252F%252Fw3.zto.com%252F%2523%252F&response_type=code&scope=userinfo,user_id,usercontact,userprofile&state=klt61aeeu3ruzpnn";
            openUrl(url);
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(".login-switch.by-static")));
            var tapElement = driver.FindElement(By.CssSelector(".login-switch.by-static"));
            tapElement.Click();

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[name=username]")));
            var passElement = driver.FindElement(By.CssSelector(@"input[name=username]"));
            passElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[name=password]")));
            var usenameElement = driver.FindElement(By.CssSelector(@"input[name=password]"));
            usenameElement.SendKeys(password);

        }

        //天使维递
        public void OpenAngelExpress(string username, string password, string otherParam)
        {
            string url = "http://tianshiweidi.com/admin/login";
            openUrl(url);
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[name='username']")));
            var passElement = driver.FindElement(By.CssSelector(@"input[name='username']"));
            passElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[name=password]")));
            var usenameElement = driver.FindElement(By.CssSelector(@"input[name=password]"));
            usenameElement.SendKeys(password);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"#container")));
            var valicodeEle = driver.FindElement(By.CssSelector(@"#container"));
            valicodeEle.Click();
        }

        //极兔快递
        public void OpenJituExpress(string username, string password, string otherParam)
        {
            string url = "https://jms.jtexpress.com.cn/login";
            openUrl(url);
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[placeholder='请输入员工编号']")));
            var usenameElement = driver.FindElement(By.CssSelector(@"input[placeholder='请输入员工编号']"));
            usenameElement.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(@"input[placeholder='请输密码']")));
            var passwordElement = driver.FindElement(By.CssSelector(@"input[placeholder='请输密码']"));
            passwordElement.SendKeys(password);

            driver.ExecuteJavaScript("var box=document.querySelector('.toggleIcon');box.remove();");
        }

        //韵达微笑计划
        public void OpenSmilePlan(string username, string password, string otherParam) {
            string url = "http://cc.yundasys.com:8877/cssp/";
            openUrl(url);
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("a")));
            var usenameElement = driver.FindElement(By.Id("a"));
            usenameElement.SendKeys(username);
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("d")));
            var passwordElement = driver.FindElement(By.Id("d"));
            passwordElement.SendKeys(password);
        }

        //新韵达魔盒
        public void OpenYunDaMoHe(string username, string password, string otherParam)
        {
            string url = "http://khd.yundasys.com";
            openUrl(url);
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(60));
            
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("customLoginpage")));
            var iframeElement = driver.FindElement(By.Id("customLoginpage"));
            var frame = driver.SwitchTo().Frame(iframeElement);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("upIcon")));
            var switchImg = frame.FindElement(By.Id("upIcon"));
            switchImg.Click();

            string selector = "body > div > div.login-container > div > div.login-header > ul > li.login-item.up-login-item";
            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.CssSelector(selector)));
            var tabBtn = frame.FindElement(By.CssSelector(selector));
            tabBtn.Click();

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("username")));
            var usernameInput = frame.FindElement(By.Id("username"));
            usernameInput.SendKeys(username);

            wait.Until(SeleniumExtras.WaitHelpers.ExpectedConditions.ElementExists(By.Id("password")));
            var passwordInput = frame.FindElement(By.Id("password"));
            passwordInput.SendKeys(password);


        }


        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: 释放托管状态(托管对象)
                }

                DestroyDriver();
                disposedValue = true;
            }
        }

        void DestroyDriver()
        {
            if (driver != null)
            {
                try
                {
                    driver.Quit();
                }
                catch (Exception)
                {
                    KillProc(driverName);
                }
            }
            else
            {
                KillProc(driverName);
            }
        }

        //~WebOpener()
        //{
        //    Dispose(disposing: false);
        //}

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }

        public override void OpenSoftware(string username, string password,string otherParam)
        {
            throw new NotImplementedException();
        }
    }
}
